<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="chinese">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">



  
  
    
      
    
    
      
    
  <script src="//cdn.jsdelivr.net/npm/pace-js@1/pace.min.js"></script>
  <link href="//cdn.jsdelivr.net/npm/pace-js@1/themes/blue/pace-theme-minimal.min.css" rel="stylesheet">







<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT">










<meta name="description" content="第十章 内部类将一个类定义放在另一个类的内部，这就是内部类。内部类和组合十完全不同的概念。 123456789101112131415161718192021222324252627282930313233343536public class Parcell &amp;#123;	class Contents&amp;#123;		private int i = 11;		public int value()&amp;#">
<meta name="keywords" content="Java Php hexo Thinking in Java">
<meta property="og:type" content="article">
<meta property="og:title" content="Thinking in Java 第十章">
<meta property="og:url" content="http://yoursite.com/2019/08/05/Thinking-in-Java-第十章/index.html">
<meta property="og:site_name" content="坚持就是胜利">
<meta property="og:description" content="第十章 内部类将一个类定义放在另一个类的内部，这就是内部类。内部类和组合十完全不同的概念。 123456789101112131415161718192021222324252627282930313233343536public class Parcell &amp;#123;	class Contents&amp;#123;		private int i = 11;		public int value()&amp;#">
<meta property="og:locale" content="chinese">
<meta property="og:updated_time" content="2020-06-04T02:30:22.247Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Thinking in Java 第十章">
<meta name="twitter:description" content="第十章 内部类将一个类定义放在另一个类的内部，这就是内部类。内部类和组合十完全不同的概念。 123456789101112131415161718192021222324252627282930313233343536public class Parcell &amp;#123;	class Contents&amp;#123;		private int i = 11;		public int value()&amp;#">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":14,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '190coder'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2019/08/05/Thinking-in-Java-第十章/">





  <title>Thinking in Java 第十章 | 坚持就是胜利</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="chinese">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">坚持就是胜利</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            Categories
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            Archives
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/08/05/Thinking-in-Java-第十章/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="190coder">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="坚持就是胜利">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Thinking in Java 第十章</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-08-05T22:21:29+08:00">
                2019-08-05
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index">
                    <span itemprop="name">Java</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="第十章-内部类"><a href="#第十章-内部类" class="headerlink" title="第十章 内部类"></a>第十章 内部类</h1><p>将一个类定义放在另一个类的内部，这就是内部类。<br>内部类和组合十完全不同的概念。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">public class Parcell &#123;</span><br><span class="line">	class Contents&#123;</span><br><span class="line">		private int i = 11;</span><br><span class="line">		public int value()&#123;</span><br><span class="line">			return i;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	class Destination&#123;</span><br><span class="line">		private String label;</span><br><span class="line">		public Destination(String whereto) &#123;</span><br><span class="line">			// TODO Auto-generated constructor stub</span><br><span class="line">			label = whereto;</span><br><span class="line">		&#125;</span><br><span class="line">		String readLabel()&#123;</span><br><span class="line">			return label;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	public Contents contents()&#123;</span><br><span class="line">		return new Contents();</span><br><span class="line">	&#125;</span><br><span class="line">	public Destination destination(String s)&#123;</span><br><span class="line">		return new Destination(s);</span><br><span class="line">	&#125;</span><br><span class="line">	public void ship(String dest)&#123;</span><br><span class="line">		Contents c = new Contents();</span><br><span class="line">		Destination d = new Destination(dest);</span><br><span class="line">		System.out.println(d.readLabel());</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Parcell p1 = new Parcell();</span><br><span class="line">		p1.ship(&quot;Inner Class&quot;);</span><br><span class="line">		Parcell p2 = new Parcell();</span><br><span class="line">		Contents c = p2.contents();</span><br><span class="line">		Parcell.Destination d = p2.destination(&quot;Class Inner&quot;);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;上面代码我们创建了一个内部类，内部类与其它类的区别在于将类隐藏在了另一个类的内部，同时如contents方法所示，外部类的方法还可以返回一个指向内部类的引用，这也是很常见的一种用法。此外我们看到main（）方法中创建的内部类对象是使用外部类的引用关联创建的，</p>
<h2 id="9-2-链接到外部类"><a href="#9-2-链接到外部类" class="headerlink" title="9.2 链接到外部类"></a>9.2 链接到外部类</h2><p>&emsp;&emsp;当我们创建了一个内部类对象，此对象就与制造它的外围对象之间有了一种关联，所以它能访问其外围对象的所有成员，而不需要任何特殊条件。此外，内部类还拥有其外围类的所有元素的访问权。<br>&emsp;&emsp;所以内部类自动拥有对其外围类所有成员的访问权限。当某个外围类的对象创建一个内部类的对象的时候，这个内部类对象必然会秘密捕获一个外围类对象的引用，也就是这个引用来选择外围类的成员。这里所有的细节都交给了编译器来处理。内部类的对象只能在其与外部类的对象相关联的时候才能被创建（在static方法中），构建内部类对象时，需要一个指向其外围类对象的引用，如果编译器访问不到这个引用就会报错，不过绝大多数情况下这种都不需要我们操心。这里也就解释了上一节关于内部类初始化方式不同的原因。意思就是在static方法中，不能通过直接的new 构造函数的形式创建内部类，因为这种形式没有将内部类与外部类对象做关联，要先创建一个外部类的对象，然后使用该对象的引用创建内部类对象。当然如果内部类是静态的，那么就没有这种要求了。<br>&emsp;&emsp;我们将上一个示例中的ship方法改成static修饰，原来的使用构造器创建内部类对象的方法就报错了。因为它没有找到关联的外部类对象引用。然后我们把这个内部类Contents改成static修饰，则编译器就不报错了。或者使用main函数中的形式，先创建一个外部类的对象，然后使用这个对象的引用去创建内部类对象。</p>
<h2 id="10-3-使用-this-与-new"><a href="#10-3-使用-this-与-new" class="headerlink" title="10.3 使用.this 与.new"></a>10.3 使用.this 与.new</h2><p>&emsp;&emsp;在内部类生成外部类对象的引用，那么可以使用外部类名.this的形式，这里如果只使用this，则返回的是内部类对象的引用。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">public class DoThis &#123;</span><br><span class="line">	void f()&#123;</span><br><span class="line">		System.out.println(&quot;This is outClass&apos;s method&quot;);</span><br><span class="line">	&#125;</span><br><span class="line">	public class Inner&#123;</span><br><span class="line">		public DoThis outer()&#123;</span><br><span class="line">			return DoThis.this;</span><br><span class="line">			//return this;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	public Inner inner()&#123;</span><br><span class="line">		return new Inner();</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		DoThis dt = new DoThis();</span><br><span class="line">		Inner in = dt.inner();</span><br><span class="line">		in.outer().f();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">// output </span><br><span class="line">This is outClass&apos;s method</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;我们不能使用new直接创建内部类对象，我们需要使用外部类对象的引用创建，这里可以使用外部类对象的引用.new语法进行创建。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">public class DoThis &#123;</span><br><span class="line">	public class Inner&#123;</span><br><span class="line">		public DoThis outer()&#123;</span><br><span class="line">			return DoThis.this;</span><br><span class="line">			//return this;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		DoThis dt = new DoThis();</span><br><span class="line">		Inner in = dt.new Inner();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="10-4-内部类与向上转型"><a href="#10-4-内部类与向上转型" class="headerlink" title="10.4 内部类与向上转型"></a>10.4 内部类与向上转型</h2><p>&emsp;&emsp;当将内部类向上转型为基类时，尤其是转型为接口时，内部类就有了用武之地。这是因为我们可以使内部类也就是接口的实现完全不可见也不可用，得到的只是基类或者接口的引用，从而更好的隐藏了实现的细节。<br></p>
<p>创建2个接口 和一个类</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public interface Destination&#123;</span><br><span class="line">	String readLabel();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public interface Contents &#123;</span><br><span class="line">	int value();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">class Parcell4&#123;</span><br><span class="line">	private class PContents implements Contents&#123;</span><br><span class="line">		private int i = 11;</span><br><span class="line">		@Override</span><br><span class="line">		public int value() &#123;</span><br><span class="line">			// TODO Auto-generated method stub</span><br><span class="line">			return i;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	protected class PDestination implements Destination&#123;</span><br><span class="line">		private String label;</span><br><span class="line">		private PDestination(String whereto) &#123;</span><br><span class="line">			// TODO Auto-generated constructor stub</span><br><span class="line">			label = whereto;</span><br><span class="line">		&#125;</span><br><span class="line">		@Override</span><br><span class="line">		public String readLabel() &#123;</span><br><span class="line">			// TODO Auto-generated method stub</span><br><span class="line">			return label;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	public Destination destination(String s)&#123;</span><br><span class="line">			return new PDestination(s);</span><br><span class="line">		&#125;</span><br><span class="line">	public Contents contents()&#123;</span><br><span class="line">			return new PContents();</span><br><span class="line">		&#125;</span><br><span class="line">&#125;</span><br><span class="line">public class TestParcell &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Parcell4 p = new Parcell4();</span><br><span class="line">		Contents c = p.contents();</span><br><span class="line">		Destination d = p.destination(&quot;Inner Class&quot;);</span><br><span class="line">		System.out.println(d.readLabel());</span><br><span class="line">		System.out.println(c.value());</span><br><span class="line">		//因为PContents是private 所以不能被访问</span><br><span class="line">		//Parcell4.PContents pc = p.new PContents();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;上面代码增加了一些新的东西，首先内部类PContents是private，除了Parcell4没有人能访问它，所以main函数最后一行编译不能通过。其次PDestination是protected的，所以除了该类本身和其子类还有同一个包中的类，其它类不能访问。因此客户端如果想访问这些实现，就受到了限制。不过我们可以看到，main函数的第二、第三行都实现了转型，也就是虽然不可见，但是不影响使用接口的实现。因此private的内部类提供了一种设计思路，通过这种方式完全阻止了依赖任何类型的编码，并且完全隐藏了实现的细节，并且由于不能访问任何新增加的、原本不属于公共接口的方法，因此接口的扩展就是没有价值的了。</p>
<p><strong>如果有对向上转型有什么作用和理解上的问题 可以参考 <a href="https://blog.csdn.net/TNTZS666/article/details/80273986" target="_blank" rel="noopener">https://blog.csdn.net/TNTZS666/article/details/80273986</a> 写的很白话易懂。</strong></p>
<h2 id="10-5-在方法和作用域内的内部类"><a href="#10-5-在方法和作用域内的内部类" class="headerlink" title="10.5 在方法和作用域内的内部类"></a>10.5 在方法和作用域内的内部类</h2><p> 有些时候我们可以将内部类创建在方法的作用域里或者是其它任何地方的作用域中，这么做有两个理由：</p>
<ol>
<li>如前所示，实现了某个类型的接口，可以创建并返回接口的引用。</li>
<li>要解决一个复杂的问题，需要一个类来辅助解决，但是又不希望这个类是公开的。<br>在方法的作用域内部创建的内部类称为局部内部类：<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">public class Parcel5 &#123;</span><br><span class="line"> public Destination destination(String s)&#123;</span><br><span class="line">  class PDestination implements Destination&#123;</span><br><span class="line">   private String label;</span><br><span class="line">   private PDestination(String whereTo)&#123;</span><br><span class="line">    label=whereTo;</span><br><span class="line">   &#125;</span><br><span class="line">   @Override</span><br><span class="line">   public String readLabel() &#123;</span><br><span class="line">    // TODO Auto-generated method stub</span><br><span class="line">    return label;</span><br><span class="line">   &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  return new PDestination(s);</span><br><span class="line"> &#125;</span><br><span class="line"> public static void main(String[] args) &#123;</span><br><span class="line">  Parcel5 p5 = new Parcel5();</span><br><span class="line">  Destination d = p5.destination(&quot;Area Inner Class&quot;);</span><br><span class="line">  System.out.println(d.readLabel());</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ol>
<p>如上所示，destination方法中的内部类实现了Destination接口，PDestination类是destination方法内部的类，所以其它地方不能访问。return语句向上转型返回了Destination，它是PDestination类的接口，也就是基类。<br>下面的例子展示在任意作用域中使用内部类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">public class Parcel6 &#123;</span><br><span class="line">	private void internalTracking(boolean b)&#123;</span><br><span class="line">		if(b)&#123;</span><br><span class="line">			class TrackingSkip&#123;</span><br><span class="line">				private String id;</span><br><span class="line">				TrackingSkip(String s)&#123;</span><br><span class="line">					id = s;</span><br><span class="line">				&#125;</span><br><span class="line">				String getSkip()&#123;</span><br><span class="line">					return id;</span><br><span class="line">				&#125;</span><br><span class="line">			&#125;</span><br><span class="line">			TrackingSkip ts = new TrackingSkip(&quot;SLIP&quot;);</span><br><span class="line">			String s = ts.getSkip();</span><br><span class="line">			System.out.println(s);</span><br><span class="line">		&#125;</span><br><span class="line">		//因为内部类在if（b）的作用域内 此处已经超过了作用范围 所以不可以使用</span><br><span class="line">		//TrackingSkip ts1 = new TrackingSkip(&quot;SLIP1&quot;);</span><br><span class="line">	&#125;</span><br><span class="line">	public void track()&#123;</span><br><span class="line">		internalTracking(true);</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Parcel6 p = new Parcel6();</span><br><span class="line">		p.track();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上边的例子主要是想在方法中判断如果入参为true则实现一个类的功能，而这个类又不想被外部可见，所以在if中创建了内部类。</p>
<h2 id="10-6-匿名内部类"><a href="#10-6-匿名内部类" class="headerlink" title="10.6 匿名内部类"></a>10.6 匿名内部类</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">public class Parcel7 &#123;</span><br><span class="line"> public Contents contents()&#123;</span><br><span class="line">  return new Contents()&#123;</span><br><span class="line">   private int i = 11;</span><br><span class="line">   @Override</span><br><span class="line">   public int value() &#123;</span><br><span class="line">    // TODO Auto-generated method stub</span><br><span class="line">    return i;</span><br><span class="line">   &#125;</span><br><span class="line">  &#125;;</span><br><span class="line"> &#125;</span><br><span class="line"> public static void main(String[] args) &#123;</span><br><span class="line">  Parcel7 p7 = new Parcel7();</span><br><span class="line">  Contents c = p7.contents();</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>contents方法内部要返回一个Contents对象的时候，我们突然加了一个类的定义，这个类没有名字，它实现了Contents接口，也就是我们实际上创建了一个继承自Contents类的匿名类对象，于是这个return对象的引用就变成了一个来自向上转型的Contents引用。上述这个匿名内部类是下面这种形式的一种简化。</p>
<p>下面是无参构造器：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">public class Parcel7 &#123;</span><br><span class="line">	public class MyContents implements Contents&#123;</span><br><span class="line">		private int i = 11;</span><br><span class="line">		@Override</span><br><span class="line">		public int value() &#123;</span><br><span class="line">			// TODO Auto-generated method stub</span><br><span class="line">			return i;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	public Contents contents()&#123;</span><br><span class="line">		return new MyContents();</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Parcel7 p7 = new Parcel7();</span><br><span class="line">		Contents c = p7.contents();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>有参构造器基类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">public class Wrapping &#123;</span><br><span class="line">	private int i;</span><br><span class="line">	public Wrapping(int x)&#123;</span><br><span class="line">		i=x;</span><br><span class="line">	&#125;</span><br><span class="line">	public int value()&#123;</span><br><span class="line">		return i;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>匿名内部类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">public class Parcel8 &#123;</span><br><span class="line">	public Wrapping wrapping(int x)&#123;</span><br><span class="line">		return new Wrapping(x)&#123;</span><br><span class="line">			public int value()&#123;</span><br><span class="line">				return super.value() * 11;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> 只需要传递合适的参数到基类的构造器中即可，虽然Wrapping只是一个普通的实现类，但是他还是被其导出类当做了公共接口来使用。<br>当匿名内部类的域要使用外部对象的引用时，需要强行将函数参数的引用设置为final才可以。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">public class Parcel8 &#123;</span><br><span class="line">	public Wrapping wrapping(final int x)&#123;</span><br><span class="line">		return new Wrapping(x)&#123;</span><br><span class="line">			public int value()&#123;</span><br><span class="line">				return super.value() * x;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="10-7-嵌套类"><a href="#10-7-嵌套类" class="headerlink" title="10.7 嵌套类"></a>10.7 嵌套类</h2><p>内部类，都是必须要有外部类关联的，也就是这些内部类有个隐式的引用，指向外部类。如果我们不需要这种关联，那么就可以将内部类显示的声明为static的，这种内部类称为嵌套类。嵌套类意味着：</p>
<ol>
<li><p>要创建嵌套类的对象，并不依赖外部对象</p>
</li>
<li><p>不能从嵌套类的对象中访问非静态的外围类对象</p>
</li>
</ol>
<p>嵌套类与普通的内部类还有一个区别，普通内部类的字段与方法，只能放在类的外部层次上，所以普通的内部类不能有static数据和static字段，也不能包含嵌套类，而嵌套类可以包含所有这些东西。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">public class Parcel11 &#123;</span><br><span class="line">	private static class ParcelContents implements Contents&#123;</span><br><span class="line">		private int i = 11;</span><br><span class="line">		@Override</span><br><span class="line">		public int value() &#123;</span><br><span class="line">			// TODO Auto-generated method stub</span><br><span class="line">			return i;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	protected static class ParcelDestination implements Destination&#123;</span><br><span class="line">		private String label;</span><br><span class="line">		private ParcelDestination(String whereTo)&#123;</span><br><span class="line">			label = whereTo;</span><br><span class="line">		&#125;</span><br><span class="line">		@Override</span><br><span class="line">		public String readLabel() &#123;</span><br><span class="line">			// TODO Auto-generated method stub</span><br><span class="line">			return label;</span><br><span class="line">		&#125;</span><br><span class="line">		public static void f()&#123;</span><br><span class="line">			//</span><br><span class="line">		&#125;</span><br><span class="line">		static int x = 8;</span><br><span class="line">		static class AnotherLevel&#123;</span><br><span class="line">			public static void funx()&#123;</span><br><span class="line">				//</span><br><span class="line">			&#125;</span><br><span class="line">			static int y = 11;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	public static Destination destination(String s)&#123;</span><br><span class="line">		return new ParcelDestination(s);</span><br><span class="line">	&#125;</span><br><span class="line">	public static Contents contents()&#123;</span><br><span class="line">		return new ParcelContents();</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Contents c = new ParcelContents();</span><br><span class="line">		Destination d = new ParcelDestination(&quot;dss&quot;);</span><br><span class="line">		Destination d1 = destination(&quot;d1&quot;);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在正常情况下，不能在接口内部放置任何代码，但是嵌套类可以作为接口的一部分，放在接口中的任何域都是public static的，所以放入的类是嵌套类，甚至我们可以使用此类实现外部接口。如果你想要创建某些公共的代码，并让它可以被某个接口的所有不同实现所共有.<br>一个内部类被嵌套多少层并不重要，重要的是它能够透明的访问它所嵌入的外围类的所有成员，即便是被定义为private的域。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">class ManyInner &#123;</span><br><span class="line">	private void f()&#123;</span><br><span class="line">		//---</span><br><span class="line">	&#125;</span><br><span class="line">	class A&#123;</span><br><span class="line">		private void g()&#123;</span><br><span class="line">			//---</span><br><span class="line">		&#125;</span><br><span class="line">		public class B&#123;</span><br><span class="line">			void h()&#123;</span><br><span class="line">				f();</span><br><span class="line">				g();</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">public class MNA&#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		ManyInner mi = new ManyInner();</span><br><span class="line">		ManyInner.A a = mi.new A();</span><br><span class="line">		ManyInner.A.B b = a.new B();</span><br><span class="line">		b.h();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> 如上可见，在嵌套了多层的内部类B中调用方法f（）和方法g（）并不需要任何其它附加条件，即便他们被定义为private。</p>
<h2 id="10-8-为什么需要内部类"><a href="#10-8-为什么需要内部类" class="headerlink" title="10.8 为什么需要内部类"></a>10.8 为什么需要内部类</h2><p>内部类实现接口与外部类实现接口的区别在于后者不是总能享用到接口带来的方便，有时需要用到接口的实现。所以使用内部类最吸引人的原因：<br>    <strong>每个内部类都能够独立的继承自一个（接口的）实现，所以无论外围类是否已经继承了某个（接口的实现），对于内部类都没有影响。</strong></p>
<p>内部类有效的实现了“多重继承”，如果在一个类中要使用两个接口，那么使用单一类和内部类看起来没有什么区别（因为单一类可以直接实现多个接口，此处不写例子了），而<strong>如果这两个接口换成是抽象类或者是具体的类，那么由于Java不支持多重继承的原因，这里使用单一类显然不能解决问题了，而内部类恰好可以有效的解决这个问题，看似是个“多重继承”。</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">//要继承的类1</span><br><span class="line">class F&#123;</span><br><span class="line">	//---</span><br><span class="line">&#125;</span><br><span class="line">//要继承的类2</span><br><span class="line">abstract class G&#123;</span><br><span class="line">	//---</span><br><span class="line">&#125;</span><br><span class="line">//外部类继承A 内部匿名类继承B</span><br><span class="line">class H extends F&#123;</span><br><span class="line">	G makeG()&#123;</span><br><span class="line">		return new G()&#123;</span><br><span class="line">			//--</span><br><span class="line">		&#125;;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">public class MutiExtends &#123;</span><br><span class="line">	static void takeF(F f)&#123;</span><br><span class="line">		//--</span><br><span class="line">	&#125;</span><br><span class="line">	static void takeG(G g)&#123;</span><br><span class="line">		//--</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		H h = new H();</span><br><span class="line">		takeF(h);</span><br><span class="line">		takeG(h.makeG());</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果不是要解决类似上边的“多重继承”问题，那么可以不实用内部类，但是使用内部类还可以获得一些其它的特性。</p>
<ol>
<li>内部类可以有多个实例，每个实例都有自己的状态信息，并且与其外部类的对象信息相互独立。</li>
<li>在单个外围类中，可以让多个内部类继承或实现多个基类。</li>
<li>创建内部类的时刻并不依赖于外围对象的创建。</li>
<li>内部类并没有令人迷惑的is-a关系，它是一个独立的实体。</li>
</ol>
<h2 id="10-9-内部类的继承"><a href="#10-9-内部类的继承" class="headerlink" title="10.9 内部类的继承"></a>10.9 内部类的继承</h2><p> 内部类由于与外部类之间有一个隐式的引用关联关系，所以在继承内部类的时候，要显示的说明他们之前的关联。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">class withInner&#123;</span><br><span class="line">	class Inner&#123;		</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">public class InheritInner extends withInner.Inner&#123;</span><br><span class="line">	InheritInner(withInner wi)&#123;</span><br><span class="line">		wi.super();</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		withInner wi = new withInner();</span><br><span class="line">		InheritInner ii = new InheritInner(wi);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在子类的构造函数中要传入继承内部类的外部类的引用。</p>
<h2 id="10-10-内部类可以被覆盖吗"><a href="#10-10-内部类可以被覆盖吗" class="headerlink" title="10.10 内部类可以被覆盖吗"></a>10.10 内部类可以被覆盖吗</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">class Egg&#123;</span><br><span class="line">	private Yolk y;</span><br><span class="line">	protected class Yolk&#123;</span><br><span class="line">		public Yolk()&#123;</span><br><span class="line">			System.out.println(&quot;Egg.Yolk&quot;);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	public Egg()&#123;</span><br><span class="line">		System.out.println(&quot;New Egg&quot;);</span><br><span class="line">		y = new Yolk();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">public class BigEgg extends Egg&#123;</span><br><span class="line">	public class Yolk&#123;</span><br><span class="line">		public Yolk()&#123;</span><br><span class="line">			System.out.println(&quot;BigEgg.Yolk&quot;);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		new BigEgg();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">//output </span><br><span class="line">New Egg</span><br><span class="line">Egg.Yolk</span><br></pre></td></tr></table></figure>

<p>基类中使用了默认的构造函数，并创建了一个内部类对象，子类中“覆盖”了内部类，所以预期的结果应该是使用子类中覆盖之后的内部类构造器。但是实际结果显然不是这样的，它还是走了正常的逻辑流程，说明子类并没有覆盖基类中内部类，这两个内部类彼此独立，在自己的命名空间中。当我们想进行类似“覆盖”内部类的功能时，可以明确的继承内部类，然后覆盖其方法。</p>
<h2 id="10-11-局部内部类"><a href="#10-11-局部内部类" class="headerlink" title="10.11 局部内部类"></a>10.11 局部内部类</h2><p>定义在方法体中内部类称为局部内部类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line">interface Counter&#123;</span><br><span class="line">	int next();</span><br><span class="line">&#125;</span><br><span class="line">public class LocalInnerClass &#123;</span><br><span class="line">	private int count = 0;</span><br><span class="line">	//局部内部类</span><br><span class="line">	Counter getCounter(final String name)&#123;</span><br><span class="line">		class LocalCounter implements Counter&#123;</span><br><span class="line">			public LocalCounter()&#123;</span><br><span class="line">				System.out.println(&quot;LocalCounter Constructor&quot;);</span><br><span class="line">			&#125;</span><br><span class="line">			@Override</span><br><span class="line">			public int next() &#123;</span><br><span class="line">				// TODO Auto-generated method stub</span><br><span class="line">				System.out.println(name);</span><br><span class="line">				return count++;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		return new LocalCounter();</span><br><span class="line">	&#125;</span><br><span class="line">	//匿名类</span><br><span class="line">	Counter getCounter2(final String name)&#123;</span><br><span class="line">		return new Counter()&#123;</span><br><span class="line">			&#123;</span><br><span class="line">				System.out.println(&quot;Counter Constructor&quot;);</span><br><span class="line">			&#125;</span><br><span class="line">			@Override</span><br><span class="line">			public int next() &#123;</span><br><span class="line">				// TODO Auto-generated method stub</span><br><span class="line">				System.out.println(name);</span><br><span class="line">				return count++;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;;</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		LocalInnerClass lc = new LocalInnerClass();</span><br><span class="line">		Counter c1 = lc.getCounter(&quot;Local Counter&quot;);</span><br><span class="line">		Counter c2 = lc.getCounter2(&quot;Annoy Counter&quot;);</span><br><span class="line">		for(int i=0;i&lt;5;i++)&#123;</span><br><span class="line">			System.out.println(c1.next());</span><br><span class="line">		&#125;</span><br><span class="line">		for(int i=0;i&lt;5;i++)&#123;</span><br><span class="line">			System.out.println(c2.next());</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>它们具有相同的行为能力，那么既然局部类在方法体外部是看不见的，那么为什么不使用匿名类呢？唯一的理由是我们需要一个已命名的构造器，或者重载构造器，而匿名类只能用于实例初始化。也就是说因为没有名字，所以没有可见的构造器。所以使用局部内部类的另一个原因就是需要不止一个该内部类的对象。</p>
<h2 id="10-12-内部类标识符"><a href="#10-12-内部类标识符" class="headerlink" title="10.12 内部类标识符"></a>10.12 内部类标识符</h2><p> 由于每个类都会产生一个.class文件，其中包含如何创建该类型的全部信息。（此信息产生一个“meta-class”,叫做class对象）所以内部类也一定会有个.class文件，它们有规范的命名规则，外围类加上“$”加上内部类的名字。</p>
<p>    如果是匿名内部类，编译器会简单的产生一个数字作为标识符，如果内部类是嵌套在别的内部类里，那么就继续使用”$”符号。</p>
<h2 id="10-13-总结"><a href="#10-13-总结" class="headerlink" title="10.13 总结"></a>10.13 总结</h2><ol>
<li>内部类是定义在一个类内部的类，这个类可以在方法中，也可以在方法外。内部类可以访问到其外部类的所有域。</li>
<li>内部类与外部类之间的关联关系是使用一个隐式的外部类引用，所以在创建内部类时，需要先创建一个外部类引用进行关联。这种形式出现在当内部类不是static修饰并且在static方法域中创建内部类对象引用的时候。</li>
<li>在内部类中，要使用外部类.this才可以返回外部类的对象引用，如果使用this只是返回了内部类的对象引用。当我们创建了一个外部类对象引用时，可以使用引用.new 内部类（）的形式创建内部类对象。</li>
<li>内部类可以用来向上转型实现接口，这种方式有效的建立了接口与实现的隔离，可以使实现完全不可见，不可修改。</li>
<li>在方法和作用域里的类，有两个作用，一个是如前所示用来实现接口并返回。另一个原因是我想创建一个类辅助我解决问题，但是不想这个类可见。</li>
<li>使用return new xx（）{} 在{}内部定义类的一些域可以创建一个实现或继承xx的匿名类，这个匿名类没有名字，也就没有构造函数。匿名类使用的外部方法引用需要被修饰为final。</li>
<li>如前所示，内部类的创建需要与外部类进行关联。如果我们不需要进行关联，那么可以将内部类修饰为static，这种称为嵌套类。嵌套类与外部类彼此独立。</li>
<li>内部类可以实现类似“多重继承”。</li>
<li>内部类与外部类的引用有关联，所以在继承内部类的时候需要显示的在构造函数中引用外部类的引用，以说明这种关联。</li>
<li>外部类被继承之后，内部类没有发生特别的变化，也就是它不会被覆盖，如果在子类中重新定义同名的内部类，这会被认为是第二个类，与之前的内部类彼此在不同的命名空间，没有关联。</li>
<li>局部内部类是定义在方法中的，作用与匿名类相同，但是有构造函数，可以进行构造函数重载。</li>
<li>所有的类都有标识符，内部类的标识符为外部类名字$内部类名字。</li>
</ol>
<p>此章节大量引用 crayoncxy 的学习笔记,大体总结很到位,(比自己总结的到位)所以读完就直接拉过来了。链接：<a href="https://crayoncxy.github.io/2018/11/15/%E3%80%90Java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3%E3%80%91%E5%8D%81%E4%B8%80%EF%BC%9A%E5%86%85%E9%83%A8%E7%B1%BB/" target="_blank" rel="noopener">https://crayoncxy.github.io/2018/11/15/%E3%80%90Java%E7%BC%96%E7%A8%8B%E6%80%9D%E6%83%B3%E3%80%91%E5%8D%81%E4%B8%80%EF%BC%9A%E5%86%85%E9%83%A8%E7%B1%BB/</a></p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/07/30/Thinking-in-Java-第九章/" rel="next" title="Thinking in Java 第九章">
                <i class="fa fa-chevron-left"></i> Thinking in Java 第九章
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/08/07/Thinking-in-Java-第十一章/" rel="prev" title="Thinking in Java 第十一章">
                Thinking in Java 第十一章 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            Table of Contents
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            Overview
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/avatar.jpg" alt="190coder">
            
              <p class="site-author-name" itemprop="name">190coder</p>
              <p class="site-description motion-element" itemprop="description">坚信持续学习就一定能超过大多数人</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">53</span>
                  <span class="site-state-item-name">posts</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">13</span>
                  <span class="site-state-item-name">categories</span>
                </a>
              </div>
            

            

          </nav>

          

          

          
          

          
          

          <div style>
  <canvas id="canvas" style="width:60%;">当前浏览器不支持canvas，请更换浏览器后再试</canvas>
</div>
<script>
(function(){

   var digit=
    [
        [
            [0,0,1,1,1,0,0],
            [0,1,1,0,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,0,1,1,0],
            [0,0,1,1,1,0,0]
        ],//0
        [
            [0,0,0,1,1,0,0],
            [0,1,1,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [1,1,1,1,1,1,1]
        ],//1
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,0,0,0],
            [0,1,1,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,0,0,0,1,1],
            [1,1,1,1,1,1,1]
        ],//2
        [
            [1,1,1,1,1,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,1,1,0],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//3
        [
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,1,0],
            [0,0,1,1,1,1,0],
            [0,1,1,0,1,1,0],
            [1,1,0,0,1,1,0],
            [1,1,1,1,1,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,1,1]
        ],//4
        [
            [1,1,1,1,1,1,1],
            [1,1,0,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,1,1,1,1,0],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//5
        [
            [0,0,0,0,1,1,0],
            [0,0,1,1,0,0,0],
            [0,1,1,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,0,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//6
        [
            [1,1,1,1,1,1,1],
            [1,1,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0]
        ],//7
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//8
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,1,1,0,0,0,0]
        ],//9
        [
            [0,0,0,0,0,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,0,0,0]
        ]//:
    ];

var canvas = document.getElementById('canvas');

if(canvas.getContext){
    var cxt = canvas.getContext('2d');
    //声明canvas的宽高
    var H = 100,W = 700;
    canvas.height = H;
    canvas.width = W;
    cxt.fillStyle = '#f00';
    cxt.fillRect(10,10,50,50);

    //存储时间数据
    var data = [];
    //存储运动的小球
    var balls = [];
    //设置粒子半径
    var R = canvas.height/20-1;
    (function(){
        var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
        //存储时间数字，由十位小时、个位小时、冒号、十位分钟、个位分钟、冒号、十位秒钟、个位秒钟这7个数字组成
        data.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
    })();

    /*生成点阵数字*/
    function renderDigit(index,num){
        for(var i = 0; i < digit[num].length; i++){
            for(var j = 0; j < digit[num][i].length; j++){
                if(digit[num][i][j] == 1){
                    cxt.beginPath();
                    cxt.arc(14*(R+2)*index + j*2*(R+1)+(R+1),i*2*(R+1)+(R+1),R,0,2*Math.PI);
                    cxt.closePath();
                    cxt.fill();
                }
            }
        }
    }

    /*更新时钟*/
    function updateDigitTime(){
        var changeNumArray = [];
        var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
        var NewData = [];
        NewData.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
        for(var i = data.length-1; i >=0 ; i--){
            //时间发生变化
            if(NewData[i] !== data[i]){
                //将变化的数字值和在data数组中的索引存储在changeNumArray数组中
                changeNumArray.push(i+'_'+(Number(data[i])+1)%10);
            }
        }
        //增加小球
        for(var i = 0; i< changeNumArray.length; i++){
            addBalls.apply(this,changeNumArray[i].split('_'));
        }
        data = NewData.concat();
    }

    /*更新小球状态*/
    function updateBalls(){
        for(var i = 0; i < balls.length; i++){
            balls[i].stepY += balls[i].disY;
            balls[i].x += balls[i].stepX;
            balls[i].y += balls[i].stepY;
            if(balls[i].x > W + R || balls[i].y > H + R){
                balls.splice(i,1);
                i--;
            }
        }
    }

    /*增加要运动的小球*/
    function addBalls(index,num){
        var numArray = [1,2,3];
        var colorArray =  ["#3BE","#09C","#A6C","#93C","#9C0","#690","#FB3","#F80","#F44","#C00"];
        for(var i = 0; i < digit[num].length; i++){
            for(var j = 0; j < digit[num][i].length; j++){
                if(digit[num][i][j] == 1){
                    var ball = {
                        x:14*(R+2)*index + j*2*(R+1)+(R+1),
                        y:i*2*(R+1)+(R+1),
                        stepX:Math.floor(Math.random() * 4 -2),
                        stepY:-2*numArray[Math.floor(Math.random()*numArray.length)],
                        color:colorArray[Math.floor(Math.random()*colorArray.length)],
                        disY:1
                    };
                    balls.push(ball);
                }
            }
        }
    }

    /*渲染*/
    function render(){
        //重置画布宽度，达到清空画布的效果
        canvas.height = 100;
        //渲染时钟
        for(var i = 0; i < data.length; i++){
            renderDigit(i,data[i]);
        }
        //渲染小球
        for(var i = 0; i < balls.length; i++){
            cxt.beginPath();
            cxt.arc(balls[i].x,balls[i].y,R,0,2*Math.PI);
            cxt.fillStyle = balls[i].color;
            cxt.closePath();
            cxt.fill();
        }
    }

    clearInterval(oTimer);
    var oTimer = setInterval(function(){
        //更新时钟
        updateDigitTime();
        //更新小球状态
        updateBalls();
        //渲染
        render();
    },50);
}

})();
</script>



        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#第十章-内部类"><span class="nav-number">1.</span> <span class="nav-text">第十章 内部类</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#9-2-链接到外部类"><span class="nav-number">1.1.</span> <span class="nav-text">9.2 链接到外部类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-3-使用-this-与-new"><span class="nav-number">1.2.</span> <span class="nav-text">10.3 使用.this 与.new</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-4-内部类与向上转型"><span class="nav-number">1.3.</span> <span class="nav-text">10.4 内部类与向上转型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-5-在方法和作用域内的内部类"><span class="nav-number">1.4.</span> <span class="nav-text">10.5 在方法和作用域内的内部类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-6-匿名内部类"><span class="nav-number">1.5.</span> <span class="nav-text">10.6 匿名内部类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-7-嵌套类"><span class="nav-number">1.6.</span> <span class="nav-text">10.7 嵌套类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-8-为什么需要内部类"><span class="nav-number">1.7.</span> <span class="nav-text">10.8 为什么需要内部类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-9-内部类的继承"><span class="nav-number">1.8.</span> <span class="nav-text">10.9 内部类的继承</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-10-内部类可以被覆盖吗"><span class="nav-number">1.9.</span> <span class="nav-text">10.10 内部类可以被覆盖吗</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-11-局部内部类"><span class="nav-number">1.10.</span> <span class="nav-text">10.11 局部内部类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-12-内部类标识符"><span class="nav-number">1.11.</span> <span class="nav-text">10.12 内部类标识符</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-13-总结"><span class="nav-number">1.12.</span> <span class="nav-text">10.13 总结</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

	
           
         
         <div style>
  <canvas id="canvas" style="width:60%;">当前浏览器不支持canvas，请更换浏览器后再试</canvas>
</div>
<script>
(function(){

   var digit=
    [
        [
            [0,0,1,1,1,0,0],
            [0,1,1,0,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,0,1,1,0],
            [0,0,1,1,1,0,0]
        ],//0
        [
            [0,0,0,1,1,0,0],
            [0,1,1,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [1,1,1,1,1,1,1]
        ],//1
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,0,0,0],
            [0,1,1,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,0,0,0,1,1],
            [1,1,1,1,1,1,1]
        ],//2
        [
            [1,1,1,1,1,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,1,1,0],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//3
        [
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,1,0],
            [0,0,1,1,1,1,0],
            [0,1,1,0,1,1,0],
            [1,1,0,0,1,1,0],
            [1,1,1,1,1,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,1,1]
        ],//4
        [
            [1,1,1,1,1,1,1],
            [1,1,0,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,1,1,1,1,0],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//5
        [
            [0,0,0,0,1,1,0],
            [0,0,1,1,0,0,0],
            [0,1,1,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,0,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//6
        [
            [1,1,1,1,1,1,1],
            [1,1,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0]
        ],//7
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//8
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,1,1,0,0,0,0]
        ],//9
        [
            [0,0,0,0,0,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,0,0,0]
        ]//:
    ];

var canvas = document.getElementById('canvas');

if(canvas.getContext){
    var cxt = canvas.getContext('2d');
    //声明canvas的宽高
    var H = 100,W = 700;
    canvas.height = H;
    canvas.width = W;
    cxt.fillStyle = '#f00';
    cxt.fillRect(10,10,50,50);

    //存储时间数据
    var data = [];
    //存储运动的小球
    var balls = [];
    //设置粒子半径
    var R = canvas.height/20-1;
    (function(){
        var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
        //存储时间数字，由十位小时、个位小时、冒号、十位分钟、个位分钟、冒号、十位秒钟、个位秒钟这7个数字组成
        data.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
    })();

    /*生成点阵数字*/
    function renderDigit(index,num){
        for(var i = 0; i < digit[num].length; i++){
            for(var j = 0; j < digit[num][i].length; j++){
                if(digit[num][i][j] == 1){
                    cxt.beginPath();
                    cxt.arc(14*(R+2)*index + j*2*(R+1)+(R+1),i*2*(R+1)+(R+1),R,0,2*Math.PI);
                    cxt.closePath();
                    cxt.fill();
                }
            }
        }
    }

    /*更新时钟*/
    function updateDigitTime(){
        var changeNumArray = [];
        var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
        var NewData = [];
        NewData.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
        for(var i = data.length-1; i >=0 ; i--){
            //时间发生变化
            if(NewData[i] !== data[i]){
                //将变化的数字值和在data数组中的索引存储在changeNumArray数组中
                changeNumArray.push(i+'_'+(Number(data[i])+1)%10);
            }
        }
        //增加小球
        for(var i = 0; i< changeNumArray.length; i++){
            addBalls.apply(this,changeNumArray[i].split('_'));
        }
        data = NewData.concat();
    }

    /*更新小球状态*/
    function updateBalls(){
        for(var i = 0; i < balls.length; i++){
            balls[i].stepY += balls[i].disY;
            balls[i].x += balls[i].stepX;
            balls[i].y += balls[i].stepY;
            if(balls[i].x > W + R || balls[i].y > H + R){
                balls.splice(i,1);
                i--;
            }
        }
    }

    /*增加要运动的小球*/
    function addBalls(index,num){
        var numArray = [1,2,3];
        var colorArray =  ["#3BE","#09C","#A6C","#93C","#9C0","#690","#FB3","#F80","#F44","#C00"];
        for(var i = 0; i < digit[num].length; i++){
            for(var j = 0; j < digit[num][i].length; j++){
                if(digit[num][i][j] == 1){
                    var ball = {
                        x:14*(R+2)*index + j*2*(R+1)+(R+1),
                        y:i*2*(R+1)+(R+1),
                        stepX:Math.floor(Math.random() * 4 -2),
                        stepY:-2*numArray[Math.floor(Math.random()*numArray.length)],
                        color:colorArray[Math.floor(Math.random()*colorArray.length)],
                        disY:1
                    };
                    balls.push(ball);
                }
            }
        }
    }

    /*渲染*/
    function render(){
        //重置画布宽度，达到清空画布的效果
        canvas.height = 100;
        //渲染时钟
        for(var i = 0; i < data.length; i++){
            renderDigit(i,data[i]);
        }
        //渲染小球
        for(var i = 0; i < balls.length; i++){
            cxt.beginPath();
            cxt.arc(balls[i].x,balls[i].y,R,0,2*Math.PI);
            cxt.fillStyle = balls[i].color;
            cxt.closePath();
            cxt.fill();
        }
    }

    clearInterval(oTimer);
    var oTimer = setInterval(function(){
        //更新时钟
        updateDigitTime();
        //更新小球状态
        updateBalls();
        //渲染
        render();
    },50);
}

})();
</script>



    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">190coder</span>

  
</div>


  <div class="powered-by">Powered by <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a></div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>





<div>
    <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
    <span class="post-meta-divider">|</span>
    <span id="busuanzi_container_site_uv">本站访客数<span id="busuanzi_value_site_uv"></span>人</span>
</div>


        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  

  
  
    <script type="text/javascript" src="//cdn.jsdelivr.net/gh/theme-next/theme-next-canvas-nest@1/canvas-nest.min.js"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
